from django.core.handlers.wsgi import WSGIRequest
from django.shortcuts import render
from django.http import HttpResponse
from virtapp.utils.libvirt_manager import virtual, clone_disk, vnc
import xml.dom.minidom
import json, os, socket, struct
from virtapp.models import VirtDirs, VirtList, VncHostList

def domain_hosts(request: WSGIRequest):
    """
        获取虚拟机
    """
    dirs = VirtDirs.objects.order_by('sort').all()
    virtual_hosts = virtual.open.getAllDomainStats()
    virtbox_map = {}
    vmbox_list = []
    hostUUIDs = []
    for host in virtual_hosts:
        hostUUIDs.append(host[0].UUIDString())
        virtbox_map[host[0].UUIDString()] = host

    # 根据分组列表获取主机
    def get_host_by_dir(uuids):
        resultHostList = []
        for uuid in uuids:
            if uuid in hostUUIDs:
                hostUUIDs.remove(uuid)
                virt = virtbox_map.pop(uuid)
                # 获取协议
                doc = xml.dom.minidom.parseString(virt[0].XMLDesc())
                protocol = (lambda graphics : graphics[0].getAttribute("type") if len(graphics)>0 else "")(
                    doc.getElementsByTagName("graphics")
                    )
                resultHostList.append({
                    "name": virt[0].name(),
                    "isDir": False,
                    "index": virt[0].UUIDString(), 
                    "isActive": virt[0].state()[0] == 1,
                    'protocol':   protocol,
                    'cpus': virt[1]['vcpu.maximum'],
                    "memory": virt[0].maxMemory()
                    })
        return resultHostList

    
    for dir in dirs:
        vmbox_list.append({ "name": dir.name, "isDir": True, "index": dir.id, "child" : get_host_by_dir([ i.uuid for i in dir.hosts.all() ])})
    # 未分组
    default_dirs = {"name": "未分组","isDir": True,"index": "default-org",'child': get_host_by_dir(hostUUIDs)}
    vmbox_list.append(default_dirs)

    return HttpResponse(json.dumps(vmbox_list), content_type="application/json")

def add_virt_dirs(request: WSGIRequest):
    """
        添加目录
    """
    name = request.POST.get("name")
    sort = request.POST.get("sort")
    dir = VirtDirs()
    dir.name = name
    dir.sort = sort
    dir.save()
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")

def del_virt_dirs(request: WSGIRequest):
    """
        删除目录
    """
    id = request.GET.get("id")
    dir = VirtDirs.objects.filter(id=id).first()
    if dir:
        dir.delete()
        return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")
    return HttpResponse(json.dumps({"status": "fail"}), content_type="application/json")

def move_host(request: WSGIRequest):
    """
        主机移动到指定的目录
    """
    id = request.POST.get("id")
    uuid = request.POST.get("uuid")
    VirtList.objects.filter(uuid=uuid).delete()
    if uuid == 'default-org':
        return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")
    dir = VirtDirs.objects.filter(id=id).first()
    if dir:
        dir.hosts.create(uuid=uuid)
        return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")
    return HttpResponse(json.dumps({"status": "fail"}), content_type="application/json")

def get_domain(request: WSGIRequest):
    """
    获取主机信息
    """
    virtual_hosts = virtual.open.getAllDomainStats()
    map = []
    if len(virtual_hosts) <= 0:
        return render(request, 'domain.html', {"map": map, "xml": " "})
    xml = virtual.open.lookupByName(virtual_hosts[0][0].name()).XMLDesc()
    for i in range(0, len(virtual_hosts)):
        host = {}
        virtual_hosts[i][0].shutdownFlags
        host["state"] = virtual_hosts[i][0].state()
        host["host"] = virtual_hosts[i][0].name()
        host["vcpu"] = virtual_hosts[i][1]["vcpu.current"]
        host["memory"] = str(virtual_hosts[i][0].maxMemory() / 1024 / 1024) + 'G'
        map.append(host)
    return render(request, 'domain.html', {"map": map, "xml": xml})


def start_domain(request: WSGIRequest):
    """
    启动虚拟机
    """
    uuid = request.POST.get("uuid")
    virtual_hosts = virtual.open.lookupByUUIDString(uuid)
    try:
        virtual_hosts.create()
    except Exception as e:
        return HttpResponse(json.dumps({"status": "fail", "msg": "启动失败: "+str(e)}), content_type="application/json")
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def shutdown_domain(request: WSGIRequest):
    """
        关机
    """
    uuid = request.POST.get("uuid")
    virtual_hosts = virtual.open.lookupByUUIDString(uuid)
    virtual_hosts.shutdown()
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def destroy_domain(request: WSGIRequest):
    """
        强制关机
    """
    uuid = request.POST.get("uuid")
    virtual_hosts = virtual.open.lookupByUUIDString(uuid)
    virtual_hosts.destroy()
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def reboot_domain(request: WSGIRequest):
    """
        重启
    """
    name = request.POST.get("name")
    virtual_hosts = virtual.open.lookupByName(name)
    virtual_hosts.reboot()
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def pause_domain(request: WSGIRequest):
    """
        挂起
    """
    name = request.POST.get("name")
    virtual_hosts = virtual.open.lookupByName(name)
    virtual_hosts.suspend()
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def add_domain(request: WSGIRequest):
    """
        添加虚拟机
    """
    name = request.GET.get("xml")
    virtual.open.defineXML(name)
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def create_domain(request: WSGIRequest):
    """
        创建虚拟机
    """
    virtual.open.createXML()
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def delete_domain(request: WSGIRequest):
    """
        删除虚拟机
    """
    name = request.POST.get("name")
    virtual_hosts = virtual.open.lookupByName(name)
    res = virtual_hosts.undefine()
    return HttpResponse(json.dumps({"status": res}), content_type="application/json")


def clone_domain(request: WSGIRequest):
    """
        克隆功能
    """
    name = request.POST.get("name")
    target = request.POST.get('target')
    virtual_hosts = virtual.open.lookupByName(name)
    domain_xml = xml.dom.minidom.parseString(virtual_hosts.XMLDesc())
    domain_xml.getElementsByTagName("name")[0].lastChild.nodeValue = target
    domain_xml.getElementsByTagName("uuid")[0].lastChild.nodeValue = ""
    for disk in domain_xml.getElementsByTagName("disk"):
        source = disk.getElementsByTagName("source")
        if len(source) == 1 and disk.getAttribute("device") == "disk":
            file = source[0].getAttribute("file")
            des_file = file[0:file.rindex("/")] + "/" + target + ".qcow2"
            clone_disk(file, des_file)
            source[0].setAttribute("file", des_file)
    virtual.open.defineXML(xml=domain_xml.toxml())
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def snap_domain(request: WSGIRequest):
    """
        创建快照
    """
    name = request.POST.get("name")
    virtual_hosts = virtual.open.lookupByName(name)
    virtual_hosts.snapshotCurrent()
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


host_memory = "./savememory/"


def save_domain(request: WSGIRequest):
    """
        存储虚拟机状态
    """
    name = request.POST.get("name")
    virtual_hosts = virtual.open.lookupByName(name)
    if not os.path.exists(host_memory):
        os.mkdir(host_memory)
    virtual_hosts.save(host_memory + name+".tmp")
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def restore_domain(request: WSGIRequest):
    """
        恢复虚拟机
    """
    name = request.POST.get("name")
    virtual_hosts = virtual.open.lookupByName(name)
    virtual_connect = virtual_hosts.connect()
    virtual_connect.restore(host_memory % name)
    return HttpResponse(json.dumps({"status": "ok"}), content_type="application/json")


def get_xml(request: WSGIRequest):
    """
        获取主机的xml
    """
    uuid = request.POST.get("uuid")
    virtual_hosts = virtual.open.lookupByUUIDString(uuid)
    defineXML = virtual_hosts.XMLDesc()
    return HttpResponse(json.dumps({"data": defineXML}), content_type="application/json")


def desktop_domain(request: WSGIRequest):
    name = request.POST.get("name")
    virtual_hosts = virtual.open.lookupByName(name)
    host = request.get_host().split(":")[0]
    domain_xml = xml.dom.minidom.parseString(virtual_hosts.XMLDesc())
    graphics = domain_xml.getElementsByTagName("graphics")
    _type = graphics[0].getAttribute("type")
    return HttpResponse(json.dumps({"status": "ok", "url": vnc.get_url(name, _type)}),
                        content_type="application/json")

def getDesktopUrl(request):
    token = request.GET.get("token")
    if(token.startswith("01-")):
        vnc_host = VncHostList.objects.filter(token=token).first()
        if not vnc_host:
            return HttpResponse(json.dumps({"status": "fail", "url": "创建失败!"}), content_type="application/json")
        return HttpResponse(socket.inet_ntoa(struct.pack("I", vnc_host.host))+ ":" + str(vnc_host.port))
    if token == "vnc":
        return HttpResponse('127.0.0.1:5901')
    virtual_hosts = virtual.open.lookupByUUIDString(token)
    domain_xml = xml.dom.minidom.parseString(virtual_hosts.XMLDesc())
    return HttpResponse('127.0.0.1:%s'% domain_xml.getElementsByTagName("graphics")[0].getAttribute("port"))

def create_domain(request: WSGIRequest):
    new_virt_host = virtual.get_template("服务器001",device=virtual.get_disk("/mnt/b.qcow2")+ virtual.get_cdrom("/mnt/x.iso"), dev="cdrom")
    try:
        virtual.open.defineXML(new_virt_host)
    except Exception as e:
        print(e)
        return HttpResponse(json.dumps({"status": "fail", "url": "创建失败!"}), content_type="application/json")
        
    return HttpResponse(json.dumps({"status": "ok", "url": "创建成功"}), content_type="application/json")
